package project.web.processor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import online.model.session.SessionAttribute;
import online.model.session.SessionUser;
import online.struts.action.UniForm;
import online.struts.chain.command.ActionRequest;
import online.struts.chain.command.ActionRequest.CommandRequest;
import online.struts.mapping.RequestMapping;

import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.chain.commands.ActionCommandBase;
import org.apache.struts.chain.contexts.ActionContext;
import org.apache.struts.chain.contexts.ServletActionContext;

import project.auth.Authentication;
import project.master.MsgUtil;
import core.config.Factory;

/**
 * アクションチェック
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class AuthenticationProcessor extends ActionCommandBase implements CommandRequest {
	/** 再ログオン */
	public static final String ID_RELOGON = "RELOGON";

	/** タイムアウトメッセージ */
	private static final String MSGID_TIME_OUT = "ZZ000000003";
	/** 未ログオンメッセージ */
	private static final String MSGID_NOT_LOGON = "ZZ000000002";

	/** 多重ログイン可否 */
	private boolean multiple = false;

	/**
	 * 多重ログイン可否取得
	 *
	 * @return 多重ログイン可否
	 */
	public boolean isMultiple() {
		return this.multiple;
	}

	/**
	 * 多重ログイン可否設定
	 *
	 * @param val 多重ログイン可否
	 */
	public void setMultiple(final boolean val) {
		this.multiple = val;
	}

	/**
	 * @see org.apache.struts.chain.commands.ActionCommandBase
	 * #execute(org.apache.struts.chain.contexts.ActionContext)
	 */
	@Override
	public boolean execute(final ActionContext context) throws Exception {
		return context.getForwardConfig() == null && ActionRequest.execute(context, this);
	}

	/**
	 * @see online.struts.chain.command.ActionRequest.CommandRequest
	 * #command(org.apache.struts.chain.contexts.ServletActionContext,
	 * online.struts.mapping.RequestMapping, online.struts.action.UniForm)
	 */
	@Override
	public boolean command(final ServletActionContext sac,
			final RequestMapping mapping, final UniForm uf) {
		// ログオンとアクションチェック
		// セッションタイムアウトチェック
		ActionForward af = checkLogon(sac.getRequest(), uf, mapping);
		if (af != null && ID_RELOGON.equals(af.getName())) {
			// メッセージ設定
			MsgUtil.putTopMessage(uf, MSGID_NOT_LOGON);
			sac.getResponse().setStatus(HttpServletResponse.SC_UNAUTHORIZED);
		}

		sac.setForwardConfig(af);

		return false;
	}

	/**
	 * ログオン確認処理
	 *
	 * @param request HTTPリクエスト
	 * @param uf 汎用フォーム
	 * @param mapping マッピング
	 * @return ActionForwardオブジェクト
	 */
	private ActionForward checkLogon(final HttpServletRequest request,
			final UniForm uf, final ActionMapping mapping) {
		// ログオンチェック
		SessionUser su = SessionAttribute.getSessionUser(request);
		if (su == null) {
			MsgUtil.putTopMessage(uf, MSGID_TIME_OUT);
			return mapping.findForward(ID_RELOGON);
		}

		if (!this.multiple) {
			Authentication auth = Factory.create(Authentication.class);
			HttpSession session = request.getSession(false);
			if (session == null || !auth.checkLogon(su.getUid(), session.getId())) {
				return mapping.findForward(ID_RELOGON);
			}

			// アクション時間設定
			auth.setActionTime(su.getUid(), uf.getDateTime(), session.getId());
		}

		return null;
	}
}
